package main

import (
	"fmt"
	"time"
)

// 定义一个简单的结构体
type Person struct {
	Name string
	Age  int
}

// 定义嵌套结构体
type Address struct {
	City    string
	Country string
}

type Employee struct {
	Person
	Address
	JobTitle string
	Salary   int
}

// 定义带有标签的结构体
type User struct {
	ID       int    `json:"id"`
	Username string `json:"username"`
	Email    string `json:"email"`
	Password string `json:"-"` // 不序列化密码
}

// 定义方法接收者
type Rectangle struct {
	Width  float64
	Height float64
}

// 为结构体定义方法
func (r Rectangle) Area() float64 {
	return r.Width * r.Height
}

func (r Rectangle) Perimeter() float64 {
	return 2 * (r.Width + r.Height)
}

// 使用指针接收者修改结构体
func (r *Rectangle) Scale(factor float64) {
	r.Width *= factor
	r.Height *= factor
}

// 定义另一个结构体和方法
type Circle struct {
	Radius float64
}

func (c Circle) Area() float64 {
	return 3.14159 * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
	return 2 * 3.14159 * c.Radius
}

func main() {
	fmt.Println("10. 结构体")

	// 创建结构体实例的方式
	fmt.Println("\n--- 创建结构体实例 ---")

	// 方式1: 按字段顺序初始化
	person1 := Person{"张三", 25}
	fmt.Printf("person1: %+v\n", person1)

	// 方式2: 使用字段名初始化（推荐）
	person2 := Person{
		Name: "李四",
		Age:  30,
	}
	fmt.Printf("person2: %+v\n", person2)

	// 方式3: 先创建再赋值
	var person3 Person
	person3.Name = "王五"
	person3.Age = 35
	fmt.Printf("person3: %+v\n", person3)

	// 方式4: 使用new创建指针
	person4 := new(Person)
	person4.Name = "赵六"
	person4.Age = 40
	fmt.Printf("person4: %+v\n", *person4)
	fmt.Printf("person4指针: %p\n", person4)

	// 匿名结构体
	student := struct {
		Name   string
		Grade  int
		Class  string
		Scores []int
	}{
		Name:   "小明",
		Grade:  10,
		Class:  "A",
		Scores: []int{90, 85, 95},
	}
	fmt.Printf("匿名结构体 student: %+v\n", student)

	// 嵌套结构体
	fmt.Println("\n--- 嵌套结构体 ---")
	employee := Employee{
		Person:   Person{Name: "张三", Age: 28},
		Address:  Address{City: "北京", Country: "中国"},
		JobTitle: "软件工程师",
		Salary:   15000,
	}
	fmt.Printf("employee: %+v\n", employee)
	// 访问嵌套字段
	fmt.Printf("员工姓名: %s, 城市: %s, 职位: %s\n", employee.Name, employee.City, employee.JobTitle)

	// 结构体标签
	fmt.Println("\n--- 结构体标签 ---")
	user := User{
		ID:       1,
		Username: "zhangsan",
		Email:    "zhangsan@example.com",
		Password: "secret123",
	}
	fmt.Printf("user: %+v\n", user)

	// 结构体方法
	fmt.Println("\n--- 结构体方法 ---")
	rect := Rectangle{Width: 10, Height: 5}
	fmt.Printf("矩形: %+v\n", rect)
	fmt.Printf("面积: %.2f\n", rect.Area())
	fmt.Printf("周长: %.2f\n", rect.Perimeter())

	// 使用指针接收者的方法
	fmt.Printf("缩放前: %+v\n", rect)
	rect.Scale(2)
	fmt.Printf("缩放后: %+v\n", rect)

	// 结构体比较
	fmt.Println("\n--- 结构体比较 ---")
	rect1 := Rectangle{Width: 5, Height: 3}
	rect2 := Rectangle{Width: 5, Height: 3}
	rect3 := Rectangle{Width: 3, Height: 5}

	fmt.Printf("rect1 == rect2: %t\n", rect1 == rect2)
	fmt.Printf("rect1 == rect3: %t\n", rect1 == rect3)

	// 结构体作为函数参数（值传递）
	fmt.Println("\n--- 结构体作为参数 ---")
	fmt.Printf("原始矩形: %+v\n", rect1)
	modifyRectangle(rect1)
	fmt.Printf("调用modifyRectangle后: %+v\n", rect1) // 原结构体不变

	// 结构体作为指针参数（引用传递）
	modifyRectanglePtr(&rect1)
	fmt.Printf("调用modifyRectanglePtr后: %+v\n", rect1) // 原结构体改变

	// 结构体切片
	fmt.Println("\n--- 结构体切片 ---")
	people := []Person{
		{Name: "张三", Age: 25},
		{Name: "李四", Age: 30},
		{Name: "王五", Age: 35},
	}
	fmt.Printf("people: %+v\n", people)

	// 遍历结构体切片
	for i, person := range people {
		fmt.Printf("索引 %d: %+v\n", i, person)
	}

	// 结构体映射
	fmt.Println("\n--- 结构体映射 ---")
	personMap := map[string]Person{
		"person1": {Name: "张三", Age: 25},
		"person2": {Name: "李四", Age: 30},
	}
	fmt.Printf("personMap: %+v\n", personMap)

	// 访问映射中的结构体
	p := personMap["person1"]
	fmt.Printf("personMap[\"person1\"]: %+v\n", p)

	// 复杂结构体示例
	type Order struct {
		ID          int
		Product     string
		Quantity    int
		Price       float64
		OrderTime   time.Time
		Customer    Person
		IsShipped   bool
		ShippedTime *time.Time
	}

	now := time.Now()
	order := Order{
		ID:        1001,
		Product:   "Go语言编程指南",
		Quantity:  1,
		Price:     59.99,
		OrderTime: now,
		Customer:  Person{Name: "张三", Age: 25},
		IsShipped: false,
	}
	fmt.Printf("订单: %+v\n", order)
}

// 值传递示例函数
func modifyRectangle(r Rectangle) {
	r.Width = 100
	fmt.Printf("modifyRectangle内部: %+v\n", r)
}

// 引用传递示例函数
func modifyRectanglePtr(r *Rectangle) {
	r.Width = 200
	fmt.Printf("modifyRectanglePtr内部: %+v\n", *r)
}
